package com.swordget.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.swordget.dao.TemplateManagerDao;
import com.swordget.entity.ColumnDesign;
import com.swordget.entity.TableDesign;
import com.swordget.entity.TemplateDesign;
import com.swordget.entity.vo.*;
import com.swordget.exception.ResolveException;
import com.swordget.exception.VerifyFailException;
import com.swordget.service.DataHandlerService;
import com.swordget.service.HandlerLogService;
import com.swordget.service.TableDefinitionService;
import com.swordget.service.TemplateManagerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.swordget.commons.SimpleFinalUtil.*;

/**
 * @Author: David
 * @Date: Created in 15:02 2020/5/12
 * @Description: 模板管理服务实现类
 * @Modified By:
 * @Version:
 */
@Slf4j
@Service
public class TemplateManagerServiceImp implements TemplateManagerService {

    private TableDefinitionService tableDefinitionService;

    private HandlerLogService handlerLogService;

    private TemplateManagerDao templateManagerDao;

    private DataHandlerService dataHandlerService;

    @Autowired
    public TemplateManagerServiceImp(TableDefinitionService tableDefinitionService, HandlerLogService handlerLogService,
                                     TemplateManagerDao templateManagerDao, DataHandlerService dataHandlerService) {
        this.tableDefinitionService = tableDefinitionService;
        this.handlerLogService = handlerLogService;
        this.templateManagerDao = templateManagerDao;
        this.dataHandlerService = dataHandlerService;
    }


    @Override
    public boolean addTemplate(SimpleRequestVo<TemplateVo> requestVo) {
        final TableDesign tableDesign = requestVo.getData().getTable();
        final TemplateVo templateVo = requestVo.getData();
        final TemplateDesign template = templateVo.getTemplate();
        final String tableId = tableDesign.getTableId();
        final String loginId = requestVo.getLoginId();
        final String fileId = requestVo.getData().getFileId();
        final String type = requestVo.getData().getHandlerType();
        //取出数据表名
        String tableName = tableDefinitionService.getTableName(loginId, tableId);
        //校验模板文件是否符合规范
        TemplateVo newTemplateVo = this.templateVerify(tableId, templateVo, fileId);
        //校验下文件类型
        String templateType = this.resolveFileType(type);

        //数据库是否存在默认模板
        int count = templateManagerDao.countByType(tableId, templateType);

        //保存到数据库中,添加其他条件
        TemplateDesign newTemplate = TemplateDesign.builder()
                .serialNo(System.currentTimeMillis() +  String.format("%06d", Math.round(Math.random() * 1000000)))
                .name(template.getName())
                .tableId(tableId)
                .tableName(tableName)
                .templateType(templateType)
                .isDefault(count > 0 ? "N" : "Y")
                .fileId(fileId)
                .createUser(loginId)
                .createDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
                .createTime(new SimpleDateFormat("HH:mm:ss").format(new Date()))
                .build();

        //将请求序列为JSON
        requestVo.getData().setTemplate(null);
        String requestJson = JSON.toJSONString(new SimpleRequestVo<>(newTemplateVo, loginId));
        newTemplate.setTemplateCont(requestJson);
        log.info("数据库模板{}", requestJson);
        boolean isAdd = templateManagerDao.save(newTemplate);
        return isAdd;
    }

    @Override
    public List<TemplateDesign> findAll(SimplePageRequestVo requestVo) {
        List<String> columns = Collections.unmodifiableList(Arrays.asList(new String[]{"SERIALNO", "NAME", "TABLENAME", "TEMPLATETYPE", "ISDEFAULT",
                "TEMPLATECONT", "FILEID", "CREATEUSER", "CREATEDATE" , "CREATETIME"}));
        List<String> types = new ArrayList<>(8);
        Collections.fill(types, "VARCHAR");
        final JSONArray queryParams = requestVo.getQueryParams();
        List<List<String>> datas = dataHandlerService.queryData(1000, 1, "TEMPLATE", queryParams, columns, types);
        //组织数据
        List<TemplateDesign> templateDesigns = datas.stream()
                .map(d -> {
                    TemplateDesign template = TemplateDesign.builder()
                            .serialNo(d.get(0))
                            .name(d.get(1))
                            .tableName(d.get(2))
                            .templateType(d.get(3))
                            .isDefault(d.get(4))
                            .templateCont(d.get(5))
                            .fileId(d.get(6))
                            .createUser(d.get(7))
                            .createDate(d.get(8))
                            .createTime(d.get(9))
                            .build();
                    return template;
                })
                .collect(Collectors.toList());
        return templateDesigns;
    }

    @Override
    public boolean remove(String serialNo) {
        return templateManagerDao.remove(serialNo);
    }


    @Override
    public boolean setDefault(String serialNo, String type) {
        if (StringUtils.isBlank(serialNo)) {
            throw new VerifyFailException("请检查您的请求参数!");
        }
        String templateType = this.resolveFileType(type);

        //调用Dao 设置默认
        return templateManagerDao.setDefault(serialNo, templateType);
    }

    /**
     * 获取模板JSON
     * @param template
     * @return
     */
    @Override
    public String findTemplateJson(String template) {
        String templateJson = templateManagerDao.findTemplateJson(template);
        if (StringUtils.isBlank(templateJson)) {
            throw new VerifyFailException("无法获取模板内容，请重新上传模板文件并重试!");
        }
        return templateJson;
    }


    private String resolveFileType(String oldType) {
        String templateType = "";
        if (EXCEL.equals(oldType) || "1".equals(oldType)) {
            templateType = "1";
        } else if (CSV.equals(oldType) || "2".equals(oldType)) {
            templateType = "2";
        } else if (TXT.equals(oldType) || "3".equals(oldType)) {
            templateType = "3";
        } else {
            throw new VerifyFailException("暂不支持此种文件类型!");
        }
        return templateType;
    }

    /**
     * 导入模板校验
     * @param tableId 数据表标识
     * @param templateVo 导入数据Vo
     * @param fileId 文件id
     */
    private TemplateVo templateVerify(String tableId, TemplateVo templateVo, String fileId) {
        //导入关系映射
        final CsvOrTxtImportVo result = templateVo.getResult();
        //请求参数基础校验
        final TemplateDesign templateDesign = templateVo.getTemplate();
        if (StringUtils.isAnyBlank(templateDesign.getName(), templateDesign.getTableId(),
                templateDesign.getTemplateType())) {
            throw new VerifyFailException("请求参数不正确,请确保填写模板名称!");
        }
        //判断数据库是否有相同的模板名称
        int count = templateManagerDao.count(templateDesign.getTableId().trim(), templateDesign.getName().trim());
        if (count > 0) {
            throw new VerifyFailException("已经存在名称相同的模板，请使用其他模板名称");
        }

        //获取模板文件
        String filePath = handlerLogService.findUploadFilePath(fileId);
        if (StringUtils.isBlank(filePath) ) {
            throw new ResolveException("无法找到解析文件,请您重新上传!");
        }

        //获取表结构
        List<ColumnDesign> columnDesigns = tableDefinitionService.getColumnDesigns(tableId, false, false);

        List<ResourceVo> resourceVos = result.getColumnMap();
        //过滤掉未选择的列和空列，也就是不用导入的列
        resourceVos = resourceVos.stream()
                .filter(r -> StringUtils.isNotBlank(r.getColumn()))
                .filter(ResourceVo::isChecked)
                .collect(Collectors.toList());
        //没有指定任何导入列
        if (resourceVos.size() <= 0) {
            throw new VerifyFailException("您没有指定任何导入列,请重试!");
        }

        //对导入列进行去重
        long resolverCount = resourceVos.stream()
                .map(ResourceVo::getColumn)
                .distinct()
                .count();
        if (resourceVos.size() != resolverCount) {
            throw new VerifyFailException("您选择要导入的列中存在重复,请重试!");
        }

        //分别解析要导入的标题和要导入的字段名
        List<String> titles = resourceVos.stream()
                .map(ResourceVo::getResource)
                .collect(Collectors.toList());
        List<String> columns = resourceVos.stream()
                .map(ResourceVo::getColumn)
                .collect(Collectors.toList());

        //判断用户是否指定了必填列
        columnDesigns.stream()
                .filter(c -> YES.equals(c.getNotNull()))
                .forEach(c -> {
                    if (!columns.contains(c.getName())) {
                        throw new VerifyFailException("你指定的导入列中必须包含必填列,请重试!");
                    }
                });


        //复制下对象
        return TemplateVo.builder()
                .result(
                        CsvOrTxtImportVo.builder()
                        .firstRow(result.getFirstRow())
                        .lastRow(result.getLastRow())
                        .headRow(result.getHeadRow())
                        .columnMap(resourceVos)
                        .sheetName(result.getSheetName())
                        .split(result.getSplit())
                        .charset(result.getCharset())
                        .build()
                )
                .template(templateDesign)
                .fileId(templateVo.getFileId())
                .handlerType(templateVo.getHandlerType())
                .table(templateVo.getTable())
                .fileId(templateVo.getFileId())
                .build();
    }





}
